﻿using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Volo.Abp.Auditing;
using Volo.Abp.Identity;
using Volo.Abp.Settings;
using Volo.Abp.Uow;
using Volo.Abp.Validation;
using IdentityUser = Volo.Abp.Identity.IdentityUser;

namespace Volo.Abp.Account.Public.Web.Pages.Account
{
	public class RegisterModel : AccountPageModel
	{
		[BindProperty(SupportsGet = true)]
		public string ReturnUrl { get; set; }

		[BindProperty(SupportsGet = true)]
		public string ReturnUrlHash { get; set; }

		[BindProperty]
		public RegisterModel.PostInput Input { get; set; }

		[BindProperty(SupportsGet = true)]
		public bool IsExternalLogin { get; set; }

		[BindProperty(SupportsGet = true)]
		public string ExternalLoginAuthSchema { get; set; }

		public virtual async Task OnGet()
		{
			await this.CheckSelfRegistrationAsync();
			if (this.IsExternalLogin)
			{
				var externalLoginInfo = await base.SignInManager.GetExternalLoginInfoAsync();
				if (externalLoginInfo != null)
				{
					if (externalLoginInfo.Principal.Identities.Any<ClaimsIdentity>())
					{
						ClaimsIdentity claimsIdentity = externalLoginInfo.Principal.Identities.First<ClaimsIdentity>();
						Claim claim = claimsIdentity.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress");
						if (claim != null)
						{
							this.Input = new RegisterModel.PostInput
							{
								EmailAddress = claim.Value
							};
						}
					}
				}
			}
		}

		[UnitOfWork]
		public virtual async Task<IActionResult> OnPostAsync()
		{
			await this.CheckSelfRegistrationAsync();
			RegisterDto registerDto = new RegisterDto
			{
				AppName = "MVC"
			};
			if (this.IsExternalLogin)
			{
				var externalLoginInfo = base.SignInManager.GetExternalLoginInfoAsync();
				if (externalLoginInfo == null)
				{
					base.Logger.LogWarning("External login info is not available", Array.Empty<object>());
					return this.RedirectToPage("./Login");
				}
				registerDto.EmailAddress = this.Input.EmailAddress;
				registerDto.UserName = this.Input.EmailAddress;
				registerDto.Password = this.GeneratePassword();
			}
			else
			{
				this.ValidateModel();
				registerDto.EmailAddress = this.Input.EmailAddress;
				registerDto.Password = this.Input.Password;
				registerDto.UserName = this.Input.UserName;
			}
			var identityUserDto = await base.AccountAppService.RegisterAsync(registerDto);
			var user = await base.UserManager.GetByIdAsync(identityUserDto.Id);
			await base.SignInManager.SignInAsync(user, true, null);
			if (this.IsExternalLogin)
			{
				await this.AddToUserLogins(user);
			}
			return base.Redirect(this.ReturnUrl ?? "/");
		}

		protected virtual async Task AddToUserLogins(IdentityUser user)
		{
			var externalLoginInfo = await base.SignInManager.GetExternalLoginInfoAsync(null);
			if (!user.Logins.Any((IdentityUserLogin x) => x.TenantId == user.TenantId && x.LoginProvider == externalLoginInfo.LoginProvider && x.ProviderKey == externalLoginInfo.ProviderKey))
			{
				user.AddLogin(new UserLoginInfo(externalLoginInfo.LoginProvider, externalLoginInfo.ProviderKey, externalLoginInfo.ProviderDisplayName));
			}
		}

		protected virtual async Task CheckSelfRegistrationAsync()
		{
			var flag = await base.SettingProvider.IsTrueAsync("Abp.Account.IsSelfRegistrationEnabled");
			if (flag)
			{
				flag = await base.SettingProvider.IsTrueAsync("Abp.Account.EnableLocalLogin");
			}
			if (flag)
			{
				throw new UserFriendlyException(base.L["SelfRegistrationDisabledMessage"]);
			}
		}

		protected virtual string GeneratePassword()
		{
			Random random = new Random();
			PasswordOptions password = base.UserManager.Options.Password;
			int num = random.Next(password.RequiredLength, IdentityUserConsts.MaxPasswordLength - 1);
			bool flag = password.RequireNonAlphanumeric;
			bool flag2 = password.RequireDigit;
			bool flag3 = password.RequireLowercase;
			bool flag4 = password.RequireUppercase;
			StringBuilder stringBuilder = new StringBuilder();
			while (stringBuilder.Length < num)
			{
				char c = (char)random.Next(32, 126);
				stringBuilder.Append(c);
				if (char.IsDigit(c))
				{
					flag2 = false;
				}
				else if (char.IsLower(c))
				{
					flag3 = false;
				}
				else if (char.IsUpper(c))
				{
					flag4 = false;
				}
				else if (!char.IsLetterOrDigit(c))
				{
					flag = false;
				}
			}
			if (flag)
			{
				stringBuilder.Append((char)random.Next(33, 48));
			}
			if (flag2)
			{
				stringBuilder.Append((char)random.Next(48, 58));
			}
			if (flag3)
			{
				stringBuilder.Append((char)random.Next(97, 123));
			}
			if (flag4)
			{
				stringBuilder.Append((char)random.Next(65, 91));
			}
			return stringBuilder.ToString();
		}

		public class PostInput
		{
			[DynamicStringLength(typeof(IdentityUserConsts), "MaxUserNameLength", null)]
			[Required]
			public string UserName { get; set; }

			[Required]
			[EmailAddress]
			[DynamicStringLength(typeof(IdentityUserConsts), "MaxEmailLength", null)]
			public string EmailAddress { get; set; }

			[DataType(DataType.Password)]
			[DynamicStringLength(typeof(IdentityUserConsts), "MaxPasswordLength", null)]
			[Required]
			[DisableAuditing]
			public string Password { get; set; }
		}
	}
}
